# -*- coding: utf-8 -*-

from random import random,randint
import math
from matplotlib import pyplot as plt

def wineprice(rating,age):
    peak_age=rating-50
  
    # Calculate price based on rating
    price=rating/2
    if age>peak_age:
        # Past its peak, goes bad in 10 years
        price=price*(5-(age-peak_age)/2)
    else:
        # Increases to 5x original value as it
        # approaches its peak
        price=price*(5*((age+1)/peak_age))
    if price<0: price=0
    return price


def wineset1():
    rows=[]
    for i in range(30):
        # Create a random age and rating
        rating=random()*50+50
        age=random()*50

        # Get reference price
        price=wineprice(rating,age)
    
        # Add some noise
        price*=(random()*0.2+0.9)

        # Add to the dataset
        rows.append({'input':(rating,age),
                 'result':price})
    return rows


def draw_result(rows):
    norm={}
    for row in rows:
        norm[row.get('input')[0]]=row.get('result')
    maxx,minx,maxy,miny = max(norm.keys()),min(norm.keys()),max(norm.values()),min(norm.values()) 
    print maxx,minx,maxy,miny 
    plt.xlim(minx,maxx)
    plt.ylim(miny,maxy)
    x=norm.keys()
    x.sort()
    y=[]
    for xx in x:
        y.append(norm.get(xx))
    plt.plot(x,y)
    plt.show()

def euclidean(v1,v2):
    d=0.0
    for i in range(len(v1)):
        d+=(v1[i]-v2[i])**2
    return math.sqrt(d)

#计算向量与训练数据的距离
def getdistance(data,vec1):
    distancelist=[]
    for i in range(len(data)):
        vec2=data[i]['input']
        distancelist.append((euclidean(vec1,vec2),i))
    distancelist.sort()
    return distancelist

#KNN估计，取前k最小距离的平均
def knnestimate(data,vec1,k=5):
    dlist=getdistance(data,vec1)
    avg=0.0
    for i in range(k):
        idx=dlist[i][1]
        avg+=data[idx]['result']
    avg/=k
    return avg

#权重反函数
def inverseweight(dist,num=1.0,const=1.0):
    return num/(dist+const)

#减法函数
def subtractweight(dist,const=1.0):
    if dist>const:
        return 0
    else:
        return const-dist

#高斯函数
def gaussian(dist,sigma=1.0):
    return math.e**(-dist**2/(2*sigma**2))

#加权knn算法
def weightedknn(data,vec1,k=5,weightf=gaussian):
    dlist=getdistance(data,vec1)
    avg=0.0
    totalweight=0.0

    for i in range(k):
        dist=dlist[i][0]
        idx=dlist[i][1]
        weight=weightf(dist)
        avg+=weight*data[idx]['result']
        totalweight+=weight

    avg/=totalweight
    return avg

if __name__ == '__main__':
    rows=wineset1()
    #draw_result(rows)
    #print knnestimate(rows,(95.0,3.0))
    print gaussian(1.0)
    print inverseweight(1.0)
    
    
    